
/*
*Pool Public Licence version 0.1 or later
*Released on 20th April 2008.
*Any voilations can be repoted at paritosh@wikiocean.net
*What is treated as voilations can be found at www.wikiocean.net/ppl1-voilations* 
******************************************************************************
* The contents of this file are subject Affero GPL v3 and later with additional conditions.
* The additional conditions are to be considered as part of the Affero GPL v3 and later.
* The additional conditions will supersede the Affero GPLv3 and later in case of conflict.
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the License at http://www.gnu.org/licenses/agpl.html
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Initial Developer of the Original Code is Paritosh Pungaliya.
* created by Paritosh Pungaliya are Copyright (C) Paritosh Pungaliya; All Rights Reserved.
* Contributions are Copyright (C) 2001-2008 Paritosh Pungaliya.

* Objective of the additional terms (license) 
* 1) Is to extend the software freedom to freedom to work.
* 2) To ensure that knowledge is free from monopoly of agencie(s).
* 3) To avoid a situation where big corporates or investors can buy out free software groups and companies and then start milking the communities built around it.
* (this trend can be seen how the openness changes in companies that get Venture Capital funding.)
* (if you agree to this logic I invite you to our group to work together)

* Additional conditions
*  0) Source code will also include
* 	a) data dictionaries, data ontologies which are used to alter the behavior of code or to control           the features of application.
* 	b) Any code generated or derived automatically or manually from this code or logic
*  1) The revenue generated by deploying, implementing , selling services and other activities
*  	 based on this source code should be shared 100%, between the people working on it.
*  2) Capital invested should be given only fixed rate of return or linked to revenue/surplus growth for limited time.
*  3) People working on the project should always have an option to replace the capital provider in full or part with lower cost capital.
*  4) Their should not be any ownership which can be sold as a claim on future profit to be generated from the work of people working on the code.
*  5) Brand thus generated should belong to the group.
*  6) For old and new members revenue sharing should be equal for same work equivalent.
*  7) The share of revenue should be decided by bidding for work before allocation of work within the group.
*  8) Before bidding various method of measuring the work should be clearly defined and published in public domain. Any change in process should also be publised in public domain imediately.
*  9) All data related to to revenue sharing should be published as and when generated in public domain.
*  10) For group of people having size more than 10 people will have to make it open online for others to participate in bids. 
*  11) All people involved in related and sub project will be treated as a group.
*  12) Once this license is being used for a certain code then all and any other software services being provided by the group should complusorilly come under 100% revenue sharing.
*  13) Cross subsidization should not happen under this revenue share, no additional benefit should be drawn from the people, by the employing agency.
*  14) Any position or knowledge or legal structure created relating to people working on code, which adversely affects the spirit of 100% revenue share will be treated as a violation.
*  15) Revenue sharing defined.
*     a) includes direct revenue and also intangible gains like brand, and organization.
*     b) No personal judgment should be involved in judging the distribution of revenue.It has to be pre-defined formula based.
*     c)100% of revenue should be shared before expenses and recievers should have control over what expenses to incur.
*     d)For the work done in any month by contributing group member, working on any project can be given revenue share from the work done by the group, for a maximum of 18 months after that month.
*     e)Revenue should be apportioned to the month in which work is done and not when received.
*  The group fulfilling the above conditions also has to be a wiki ecosystem further defined in www.wekosystem.org or read about Wekosystem at www.wikiocean.net

*  ******************************************************************************
*/  
package calculation;

import java.util.Hashtable;

import database.RecordSearch;
import dbmanager.Column;
import dbmanager.DBManager;
import dbmanager.GetIdName;
import file.SearchRecord;

import sort.ArraySort;
import utility.Input;
import utility.ReadFile;
/**
 * /**
 * @author
 * TestExpression This class Produces the result of specified 
 *  calculation .
 */
 public class Expression 
{
	boolean FLAG= false;
	public String returnRecord="";
	public String TableId="";
	public String Expression="";
	public String Expressiontable="";
	GetIdName gin;
	DBManager dbSQL;
	String TABLENAME="tablename";
	//String MasterPath = "C://Reports//Basic_Reports//Master_Reports//";
	//String fileFormat = ".txt";
	ReadFile rFile = new ReadFile();
	
	//RandomAccessFile raf;
	int PVOrder = 0;
	int RefOrder = 0;
	//FileUtility file;
	/**
	 * Create Object of hashtable to put the value of expression
	 */ 
	public Hashtable<Object,Object> TransactionMap = new Hashtable<Object,Object>(); 
	public Hashtable<Object,Object>TransactionDetailMap =  new Hashtable<Object,Object>();
	
	public Expression(DBManager dbSQL, Hashtable<Object,Object> TransactionMap, Hashtable<Object,Object>TransactionDetailMap) 
	{
		this.dbSQL = dbSQL;
		gin = new GetIdName(dbSQL);
		TABLENAME = gin.getId(TABLENAME);
		this.TransactionMap.putAll(TransactionMap);
		this.TransactionDetailMap.putAll(TransactionDetailMap);
	}
	/**
	 * Expression() This is parametrise constructor 
	 * @param db Get the referenced of DBManager  
	 */
	public Expression(DBManager db) {
		
		this.dbSQL = db;
		gin = new GetIdName(dbSQL);
	}
/**
 * setExpression() This method is used to set the value of expression
 * @param expression_id Gets the String value of expression
 * @exception Exception
 */ 
	public boolean setExpression(String expression_id)
	{
		try 
		{
			String value_id = gin.getId("Value");
			String Return_id = gin.getId("Return");
			System.out.println("calculation::Calculation::getExpression()::Expression : "+expression_id);
			RecordSearch rs=new RecordSearch(dbSQL);
			Hashtable<Object, Object> hasht = new Hashtable<Object, Object>();
			hasht.clear();
			hasht.put("mid", expression_id);
			hasht.put("pid",value_id);
			hasht.put("td", "null");
			rs.setConditionMap(hasht);
			String exp[] = rs.getArrayFromResultSet();
			int VTOrder=0;
			String Values[] = exp[0].split("\t");
			try
			{
				//raf = new RandomAccessFile(trans_type_path,"r");
				//FileUtility file = new FileUtility(raf);
				//VTOrder = file.getColumnIndex("VT")-1;
				VTOrder = Column.vt_index-1; 
				//raf.close();
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
			Expression = Values[VTOrder];
			System.out.println("calculation::Calculation::getExpression():: Expression : "+Expression);
			
			hasht.clear();
			hasht.put("mid", expression_id);
			hasht.put("pid", TABLENAME);
			rs.setConditionMap(hasht);
			String temp = rs.getArrayFromResultSet()[0];
			String temprecord[] = temp.split("\t");
			Expressiontable = temprecord[Column.pv_index-1];
			if(Expressiontable.equals("0"))
				Expressiontable = temprecord[Column.vt_index-1];
			else
				Expressiontable = gin.getItem(Expressiontable);
			hasht.clear();
			hasht.put("mid", expression_id);
			hasht.put("pid", Return_id);
			rs.setConditionMap(hasht);
			temp = rs.getArrayFromResultSet()[0];
			temprecord = temp.split("\t");
			
			int index = temprecord[VTOrder].indexOf(">");
			TableId = temprecord[VTOrder].substring(0,index);
			returnRecord = temprecord[Column.pv_index-1];
			if(returnRecord.equals("0"))
				returnRecord = temprecord[VTOrder].substring(index+1);
			else
			{
				returnRecord = gin.getItem(returnRecord);
				returnRecord = returnRecord.substring(index+1);
			}
			
			return true;
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
			return false;
		}
		//Return Value
	}
	/**
	 *parse() This method is used to parse the value of expression
	 * @param Expression Gets the String value of expression
	 * @exception Exception
	 * @return double value of expression
	 */ 
	public double parse(String Expression)
	{
		Expressionsubstring expSub = new Expressionsubstring(dbSQL,TransactionMap,TransactionDetailMap);
		String SplitChar = "!";
		
		System.out.println("calculation::Expression::parse(): Expression : "+Expression);
		String Precedence_id = gin.getId("OperatorPrecedence");
		String Operator_id = gin.getId("Operator");
		Hashtable<Object, Object> condition =new Hashtable<Object, Object>();
		condition.put("mid",Precedence_id);
		condition.put("td", "null");
		RecordSearch rs =new RecordSearch(dbSQL);
		rs.setConditionMap(condition);
		String result[] = rs.getArrayFromResultSet();
		StringBuffer Record = rFile.searchObject(result, Operator_id, SplitChar);
		
		try
		{
			//raf = new RandomAccessFile(trans_type_path,"r");
			//file = new FileUtility(raf);
			//PVOrder = file.getColumnIndex("PV")-1;
			//RefOrder = file.getColumnIndex("Ref")-1;;
			PVOrder = Column.pv_index-1;
			RefOrder = Column.ref_index-1;
		}
		catch (Exception e) 
		{
			e.printStackTrace();
			System.out.println("calculation::Expression::Parse(): Order of Property Details are not found");
		}
		int precedenceOrder=1;
		
		ArraySort sort = new ArraySort(dbSQL);
		String [] RecordSet = sort.sortArrayIndex(Record.toString().split(SplitChar),RefOrder);
		for(int i=0;i<RecordSet.length;i++)
		{
		
			String [] Values = RecordSet[i].split("\t");
			RecordSet[i]= gin.getItem(Values[PVOrder]);
			//System.out.println("Sorted Operators are : "+recordSet);
		}
		
		for(int i=0;i<RecordSet.length;i++)
		{
			String Operator = RecordSet[i];
			System.out.println("calculation::Expression::parse(): The Operator is : "+Operator);
			if(i < 1)
			{
				int beginIndex =0;
				String temp = Expression;
				while(true)
				{
					if(temp.contains(Operator))
					{
						int start =  temp.indexOf(Operator);
						beginIndex = beginIndex+start+1;
						temp = temp.substring(start+1);
						if(temp.contains(Operator))
						{
							continue;
						}
						else
						{
							int end = temp.indexOf(RecordSet[i+1]);
							temp = temp.substring(0, end);
							System.out.println("calculation::Expression::parse(): The String is : "+RecordSet[i]+temp+RecordSet[i+1]);
							
							//System.out.println("calculation::Expression::parse(): Begining Index is : "+beginIndex);
							end = beginIndex+end;
							//System.out.println("calculation::Expression::parse(): End Index is : "+end);
							System.out.println("calculation::Expression::parse():The Exp is : "+Expression.substring(beginIndex-1,end+1));
							
							StringBuffer expression = new StringBuffer(Expression);
							String replace = expSub.getResult(temp, RecordSet);
							expression.replace(beginIndex-1, end+1, replace);
							Expression = expression.toString();
							
							// Check if the calculation is completed or not
							try
							{
								FLAG = true;
								Double.parseDouble(Expression);
								return Double.parseDouble(Expression);
							}
							catch (Exception e) 
							{
								FLAG = false;
							}
							if(FLAG == false)
							{
								System.out.println("calculation::Expression::parse():Call Expression : "+Expression);
								parse(Expression);
							}
							System.out.println("calculation::Expression::parse():The New Expression String is : "+Expression);
						}
					}
					else 
					{
						precedenceOrder = precedenceOrder+2;
						break;
					}
				}
			}
			else
			{
				Expression = expSub.getResult(Expression, RecordSet);
				//Check if the calculation is completed or not
				try
				{
					Double.parseDouble(Expression);
					return Double.parseDouble(Expression);
				}
				catch (Exception e) 
				{
					e.printStackTrace();
				}
				if(Expression.equals("error"))
				{
					System.out.println("calculation::Expression::parse():Error Occured : ");
					return 0;
				}
			}
		}
		return Double.parseDouble(Expression);
	}

/*	private String [] OperatorSorting(String[] recordSet)
	{
		String [] sortedOperators = recordSet;
		for(int j=0;j<recordSet.length;j++)
		{
			String []Values = recordSet[j].split("\t");
			int Precedence = Integer.parseInt(gin.getItem(Values[RefOrder]));
			int min = Precedence;
			for(int i=j+1;i<recordSet.length;i++)
			{
				Precedence = Integer.parseInt(gin.getItem(Values[RefOrder]));
				if(min < Precedence)
				{
					String temp = recordSet[j];
					recordSet[j] = recordSet[i];
					recordSet[i] = temp;
					min = Precedence;
				}
			}
		}
		for(int i=0;i<recordSet.length;i++)
		{
		
			String [] Values = recordSet[i].split("\t");
			sortedOperators[i]= gin.getItem(Values[PVOrder]);
			//System.out.println("Sorted Operators are : "+recordSet);
		}
		return sortedOperators;
	}
*/	
	public static void main(String [] a)
	{
		DBManager db = new DBManager();
		db.getConnect();
		Expression exp = new Expression(db);
		System.out.println(exp.parse("2222+4444*111/222"));
	}
}

